Unreal C++ Multiplayer Master: Intermediate Game Development (1)
카테고리: Unreal Engine
Chapter 1 Puzzle Platforms - Connecting Players
01-1 Course Promo
- So this course isn’t for beginners Like a lot of our courses, it actually requires that you have experience making a couple of games with Unreal and C++
01-2 Introduction to Puzzle Platforms
- So, yeah, let’s get started in to this section where we’re going to be once again connecting between instances on the same machine or on the local network and getting a general overview of how the multiplayer space looks with unreal
01-3 Differences Between UE5 and UE4
- So in this vignette we’ve seen how Unreal four and Unreal five are actually more similar than they at first appear
01-4 Connecting Two Players
- What happen Under the Hood? (1) Unreal loads the Map (2) The Map specifies a GameMode (3) The PlayerController joins the Map (4) It asks the GameMode to spawn a Pawn (5) The Pawn is linked th the PlayerController
01-5 How to Be an Active Student
- (1) Lecture Project Changes (2) This Lecture Discussions (3) Course Slides (4) Udemy QnA, Please use brace to attach the code (5) Discord
01-6 Surveying the Multiplayer Space
- Session-Based Stages (1) Discovery (2) Connection (3) Synchronisation
01-7 Meet the Client-Server Model
01-8 Tips For Not Spawning
- Connect error solution
01-9 Detecting Where Code is Running
AMovingPlatform::AMovingPlatform()
{
PrimaryActorTick.bCanEverTick = true;
// Now this actor can move
// 주의할 점은 생성자에서 무언가를 변경해도
// 월드에 배치되거나 블루프린트로 생성된 오브젝트는 변경되지 않는다
SetMobility(EComponentMobility::Movable);
}
void AMovingPlatform::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
// The code that we write runs both on the server and the client in exactly the same way
// The only difference being that there are some method calls that allow us to detect
// Whether we are the client or whether we are the server
// Namely that method call is has authority
// If server returns true else return false
if (HasAuthority())
{
FVector Location = GetActorLocation();
Location += FVector(Speed * DeltaTime, 0, 0);
SetActorLocation(Location);
}
}
01-10 Authority and Replication
void AMovingPlatform::BeginPlay()
{
Super::BeginPlay();
if (HasAuthority())
{
// 이 액터가 네트워크 클라이언트에 복제되는지 여부를 설정합니다
SetReplicates(true);
// 이 액터의 움직임이 네트워크 클라이언트에 복제되는지 여부를 설정합니다
SetReplicateMovement(true);
}
}
void AMovingPlatform::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
//------------------------------------------------------------------------
// 코드를 만약 이렇게 바꾸면 클라에서만 큐브가 움직인다
// 하지만 서버가 기준이기 때문에 클라 캐릭터가 큐브가
// 원래 있던 위치에 박치기 하면 충돌이 일어난다
// 이 상태에서 만약 서버 캐릭터가 큐브위에 올라서면
// 클라이언트 큐브가 서버 캐릭터를 옮길것이다 하지만
// 진실은 서버 캐릭터와 서버 큐브는 안움직이고 있다
// 본문에서는 이것을 아래와 같이 설명하고 있다
// Unreal builds basically will move when something is attached to moves
// Something when it's standing on top of something, then it moves
//------------------------------------------------------------------------
if (!HasAuthority())
{
FVector Location = GetActorLocation();
Location += FVector(Speed * DeltaTime, 0, 0);
SetActorLocation(Location);
}
}
01-11 Widgets For FVector Properties
class PUZZLEPLATFORMS_API AMovingPlatform : public AStaticMeshActor
{
GENERATED_BODY()
//..
// 위의 사진 처럼 Target 다이아 몬드를 생성해주려면 어떻게 해야 하는가?
// MakeEditWidget = true로 세팅해준다
UPROPERTY(EditAnywhere, Meta = (MakeEditWidget = true))
FVector TargetLocation;
};
01-12 Sending The Platform Back
if (HasAuthority())
{
// Target Swap을 아래 코드처럼 거리기반으로 해주는 이유는 무엇인가?
// Position 기반으로 코드를 작성하면 속도가 너무 빠를때 해당 Position을
// 지나쳐 무한히 움직일 수 있기 때문이다
FVector Location = GetActorLocation();
float JourneyLength = (GlobalTargetLocation - GlobalStartLocation).Size();
float JourneyTravelled = (Location - GlobalStartLocation).Size();
if (JourneyTravelled >= JourneyLength)
{
// GlobalStartLocation은 Local 좌표인가 World 좌표인가?
// World 좌표
FVector Swap = GlobalStartLocation;
GlobalStartLocation = GlobalTargetLocation;
GlobalTargetLocation = Swap;
}
FVector Direction = (GlobalTargetLocation - GlobalStartLocation).GetSafeNormal();
Location += Speed * DeltaTime * Direction;
SetActorLocation(Location);
}
01-13 Set Up A Simple Puzzle
01-14 Playing Over The Internet
- C:\UE_4.17\Engine\Binaries\Win64\UE4Editor.exe D:\Puzzle_Platforms\PuzzlePlatforms\PuzzlePlatforms.uproject 000.000.000.000 -game -log
01-15 Set Up A Platform Trigger
APlatformTrigger::APlatformTrigger()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
// TriggerVolume 라는 이름으로 컴포넌트를 생성했다
TriggerVolume = CreateDefaultSubobject<UBoxComponent>(FName("TriggerVolume"));
if (!ensure(TriggerVolume != nullptr)) return;
RootComponent = TriggerVolume;
}
01-16 Handling Overlap Events in C++
// 충돌 이벤트를 생성하기 위한 주요 과정을 설명하면?
// 1. Dynamic 등록
TriggerVolume->OnComponentBeginOverlap.AddDynamic(this, &APlatformTrigger::OnOverlapBegin);
TriggerVolume->OnComponentEndOverlap.AddDynamic(this, &APlatformTrigger::OnOverlapEnd);
// 2. 충돌 함수 정의
void APlatformTrigger::OnOverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
UE_LOG(LogTemp, Warning, TEXT("Activated"));
}
void APlatformTrigger::OnOverlapEnd(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
UE_LOG(LogTemp, Warning, TEXT("Deactivated"));
}
01-17 Activating Platforms From Triggers
01-18 When To Use A GameInstance
class PUZZLEPLATFORMS_API UPuzzlePlatformsGameInstance : public UGameInstance
{
GENERATED_BODY()
public:
UPuzzlePlatformsGameInstance(const FObjectInitializer& ObjectInitializer);
// 이 함수에 대해 설명하면?
// UGameInstance에 있는 함수를 오버라이딩한 함수이다
virtual void Init();
};
01-19 Console Commands With Exec
class PUZZLEPLATFORMS_API UPuzzlePlatformsGameInstance : public UGameInstance
{
GENERATED_BODY()
public:
UPuzzlePlatformsGameInstance(const FObjectInitializer& ObjectInitializer);
virtual void Init();
// 이 함수의 용도는 무엇인가?
// 콘솔 창에서 실행시킬 명령어를 정의한다
UFUNCTION(Exec)
void Host();
UFUNCTION(Exec)
void Join(const FString& Address);
};
- logging to the screen unreal 라고 구글에 검색하면 디버깅 메시지 출력 가이드를 볼 수 있다
01-20 Hosting Servers With ServerTravel
- (1) Player controllers will connect in to the map (2) We’ve got three players all playing around in the same map (3) Server can execute a command called server travel and say, oh, there’s another map (4) All to move over their server, travel to map number two, in this case, Africa map (5) All the servers, one by one, have to reconnect to the new map and move themselves into the new map so the controllers don’t get destroyed They just get moved into a new map
void UPuzzlePlatformsGameInstance::Host()
{
UEngine* Engine = GetEngine();
if (!ensure(Engine != nullptr)) return;
Engine->AddOnScreenDebugMessage(0, 2, FColor::Green, TEXT("Hosting"));
UWorld* World = GetWorld();
if (!ensure(World != nullptr)) return;
// 이 함수의 역할은?
// 월드 이동
World->ServerTravel("/Game/ThirdPersonCPP/Maps/ThirdPersonExampleMap?listen"); // ?listen 구문이 없으면 어떻게 될까? 따로 공부하자
}
01-21 Joining Servers With ClientTravel
- Understand the difference between client travel and server travel, Client travel that operates on a player controller level and it tells the individual player controller that it should move
void UPuzzlePlatformsGameInstance::Join(const FString& Address)
{
UEngine* Engine = GetEngine();
if (!ensure(Engine != nullptr)) return;
Engine->AddOnScreenDebugMessage(0, 5, FColor::Green, FString::Printf(TEXT("Joining %s"), *Address));
APlayerController* PlayerController = GetFirstLocalPlayerController();
if (!ensure(PlayerController != nullptr)) return;
// 이 함수의 용도는 무엇인가?
// Client travel을 하기위한 용도
PlayerController->ClientTravel(Address, ETravelType::TRAVEL_Absolute);
}
01-22 Sharing Your Game On itch.io
- https://itch.io/ 이 사이트는 스팀과 달리 무료로 게임을 배포해 볼 수 있다
댓글남기기